package com.akcome.apollo.service.impl;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.common.utils.bean.AkResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.ui.ModelMap;

import com.akcome.apollo.common.AkResultHelper;
import com.akcome.apollo.common.ApolloConstants;
import com.akcome.apollo.common.AuthUtils;
import com.akcome.apollo.common.MathUtil;
import com.akcome.apollo.common.TokenHelper;
import com.akcome.apollo.domain.BmpAccount;
import com.akcome.apollo.domain.BmpAccountWallet;
import com.akcome.apollo.domain.VStatsUsersDay;
import com.akcome.apollo.domain.VStatsUsersHour;
import com.akcome.apollo.domain.resultcode.CommonResultCode;
import com.akcome.apollo.domain.resultcode.UserResultCode;
import com.akcome.apollo.dto.AccountAcceptDto;
import com.akcome.apollo.dto.PoolSpeedBean;
import com.akcome.apollo.dto.SpeedData;
import com.akcome.apollo.dto.SpeedDataResult;
import com.akcome.apollo.repository.BmpAccountRepository;
import com.akcome.apollo.service.BmpAccountService;
import com.akcome.apollo.service.BmpAccountWalletService;
import com.akcome.apollo.service.BmpIncomeService;
import com.akcome.apollo.service.VMiningWorkersService;
import com.akcome.apollo.service.VStatsUsersDayService;
import com.akcome.apollo.service.VStatsUsersHourService;


/**
 * 用户账户信息Service接口实现
 *
 * @author wn
 * @version $v: 1.0.0, $time:2017-12-26 08:49:00 Exp $
 */
@Service
public class BmpAccountServiceImpl implements BmpAccountService {

	private Logger logger = LoggerFactory.getLogger(this.getClass());
	
	@Autowired
	private TokenHelper tokenHelper;

	@Autowired
	private BmpAccountRepository bmpAccountRepository;
	
	@Autowired
	private VMiningWorkersService vMiningWorkersService;
	
	@Autowired
	private VStatsUsersDayService vStatsUsersDayService;
	
	@Autowired
	private VStatsUsersHourService vStatsUsersHourService;
	
	@Autowired
	private BmpAccountWalletService bmpAccountWalletService;
	
	@Autowired
	private AkResultHelper akResultHelper;
	
	@Autowired
	private BmpIncomeService bmpIncomeService;
	
	@Override
	public BmpAccount save(BmpAccount bmpAccount){
		return bmpAccountRepository.save(bmpAccount);
	}
	
	@Override
	public BmpAccount findOne(Long id){
		return bmpAccountRepository.findOne(id);
	}
	
	@Override
	public List<BmpAccount> findByUserId(Long userId){
		return bmpAccountRepository.findByUserId(userId);
	}
	
	@Override
	public BmpAccount findByUserIdAndName(Long userId,String name){
		return bmpAccountRepository.findByUserIdAndName(userId, name);
	}
	
	@Override
	public int countByIdAndUserId(Long id,Long userId){
		return bmpAccountRepository.countByIdAndUserId(id, userId);
	}
	
	@Override
	public void homeUserSetting(Map<String, Object> modelMap) {
		Long accountId = (Long)modelMap.get("accountId");
		if(null!=accountId){
			//当前币种
			String coinType = (String) modelMap.get("coinType");
			//旷工总数
			int totalMine = vMiningWorkersService.countByPuid(accountId,coinType);
			//有效旷工数
			int runMine = vMiningWorkersService.countByActive(accountId,coinType);
			//查询待支付
			Double sumEarn = bmpIncomeService.sumEarn(accountId, coinType);
			//历史总收益
			Double totalIncome = bmpIncomeService.sumEarn(accountId, coinType);

			//昨日收益
			Date date = DateUtils.addDays(new Date(), -1);
			SimpleDateFormat sf = new SimpleDateFormat("yyyyMMdd");
			Double yesterdayIncome = bmpIncomeService.sumAmountByAccountIdAndCoinTypeAndDate(accountId, coinType, sf.format(date));
			
			//当前账户分段算力
			AccountAcceptDto accountAcceptDto = vMiningWorkersService.sumAcceptBypuid(accountId, coinType);
			
			modelMap.put("totalMine", totalMine);
			modelMap.put("runMine", runMine);
			modelMap.put("sumEarn", sumEarn);
			modelMap.put("income24", yesterdayIncome);
			modelMap.put("totalIncome", totalIncome);
			if(null!=accountAcceptDto){
				accountAcceptDto.setSpeed1m(MathUtil.div(MathUtil.mul(accountAcceptDto.getAccept1m().doubleValue(), Math.pow(256, 4)), MathUtil.mul(Math.pow(10, 12),60), 2));
				accountAcceptDto.setSpeed5m(MathUtil.div(MathUtil.mul(accountAcceptDto.getAccept5m().doubleValue(), Math.pow(256, 4)), MathUtil.mul(Math.pow(10, 12),60*5), 2));
				accountAcceptDto.setSpeed15m(MathUtil.div(MathUtil.mul(accountAcceptDto.getAccept15m().doubleValue(), Math.pow(256, 4)), MathUtil.mul(Math.pow(10, 12),60*15), 2));
				accountAcceptDto.setSpeed1h(MathUtil.div(MathUtil.mul(accountAcceptDto.getAccept1h().doubleValue(), Math.pow(256, 4)), MathUtil.mul(Math.pow(10, 12),60*60), 2));
			}
			modelMap.put("accountAcceptDto", accountAcceptDto);
		}
	}
	
	@Override
	public SpeedDataResult speedData(Long accountId,String type) throws Exception{
		List<SpeedData> speedDatas = new ArrayList<SpeedData>();
		Date endDate = new Date();
		BmpAccount bmpAccount = findOne(accountId);
		String coinType = bmpAccount.getCoinType();
		List<PoolSpeedBean> poolSpeedBeanList = new ArrayList<PoolSpeedBean>();
		
		if("hour".equals(type)){
			//查询近36小时内数据
			SimpleDateFormat sf = new SimpleDateFormat("yyyyMMddHH");
			//组装数据
			Date beginDate = DateUtils.addHours(endDate, -36);
			Date tempDate = beginDate;
			do {
				tempDate = DateUtils.addHours(tempDate, 1);
				PoolSpeedBean poolSpeedBean = new PoolSpeedBean();
				poolSpeedBean.setDate(sf.format(tempDate));
				poolSpeedBean.setSpeed(0D);
				poolSpeedBeanList.add(poolSpeedBean);
				
			} while (tempDate.getTime()<endDate.getTime());
			
			//计算算力
			List<VStatsUsersHour> vStatsUsersHours = vStatsUsersHourService.findByPuidAndhourBetween(accountId, sf.format(beginDate), sf.format(endDate),coinType);
			for (VStatsUsersHour vStatsUsersHour : vStatsUsersHours) {
				for (PoolSpeedBean speedBean : poolSpeedBeanList) {
					if(speedBean.getDate().equals(vStatsUsersHour.getHour().toString())){
						speedBean.setSpeed(MathUtil.div(MathUtil.mul(vStatsUsersHour.getAccept().doubleValue(), Math.pow(256, 4)), MathUtil.mul(Math.pow(10, 12),60*60), 2));
					}
				}
			}
			
			//处理最后一条数据
			PoolSpeedBean speedBean = poolSpeedBeanList.get(poolSpeedBeanList.size()-1); 
			double speed = speedBean.getSpeed();
			if(speed >0D){
				int minutes =  Integer.parseInt(new SimpleDateFormat("m").format(endDate));
				if(minutes>0){
					speedBean.setSpeed(MathUtil.div(MathUtil.mul(speed, 60),minutes, 2));
					poolSpeedBeanList.set(poolSpeedBeanList.size()-1, speedBean);
				}
			}
			
		}else if("day".equals(type)){
			//查询近一个月
			SimpleDateFormat sf = new SimpleDateFormat("yyyyMMdd");
			//组装数据
			Date beginDate = DateUtils.addMonths(endDate, -1);
			Date tempDate = beginDate;
			do {
				tempDate = DateUtils.addDays(tempDate, 1);
				PoolSpeedBean poolSpeedBean = new PoolSpeedBean();
				poolSpeedBean.setDate(sf.format(tempDate));
				poolSpeedBean.setSpeed(0D);
				poolSpeedBeanList.add(poolSpeedBean);
				
			} while (tempDate.getTime()<endDate.getTime());
			//计算算力
			List<VStatsUsersDay>  vStatsUsersDays = vStatsUsersDayService.findByPuidAndhourBetween(accountId, sf.format(beginDate), sf.format(endDate),coinType);
			for (VStatsUsersDay statsUsersDay : vStatsUsersDays) {
				for (PoolSpeedBean speedBean : poolSpeedBeanList) {
					if(speedBean.getDate().equals(statsUsersDay.getDay().toString())){
						speedBean.setSpeed(MathUtil.div(MathUtil.mul(statsUsersDay.getAccept().doubleValue(), Math.pow(256, 4)), MathUtil.mul(Math.pow(10, 12),60*60*24), 2));
					}
				}
			}
			//处理最后一条数据
			PoolSpeedBean speedBean = poolSpeedBeanList.get(poolSpeedBeanList.size()-1); 
			double speed = speedBean.getSpeed();
			if(speed >0D){
				int hour =  Integer.parseInt(new SimpleDateFormat("H").format(endDate));
				if(hour>0){
					speedBean.setSpeed(MathUtil.div(MathUtil.mul(speed, 24),hour, 2));
					poolSpeedBeanList.set(poolSpeedBeanList.size()-1, speedBean);
				}
			}
			
			
		}

		SpeedData speedData = new SpeedData();
		speedData.setCoin(coinType);
		speedData.setUnit("T/s");
		speedData.setPoolSpeedBeanList(poolSpeedBeanList);
		speedDatas.add(speedData);
		SpeedDataResult speedDataResult = new SpeedDataResult();
		speedDataResult.setSpeedData(speedDatas);
		return speedDataResult;
	}
	
	@Override
	public AkResult delete(Long id){
		
		Long userId = AuthUtils.getUserId();
		
		int count = countByIdAndUserId(id, userId);
		if(count==0){
			return akResultHelper.buildFailAkResult(CommonResultCode.PARAM_ERROR);
		}
		
		List<BmpAccountWallet> accountWallets = bmpAccountWalletService.findByAccountId(id);
		if(CollectionUtils.isNotEmpty(accountWallets)){
			return akResultHelper.buildFailAkResult(UserResultCode.NOT_DEL_HAS_CHILD);
		}
		
		int incomeCount = bmpIncomeService.countByAccountId(id);
		if(incomeCount>0){
			return akResultHelper.buildFailAkResult(UserResultCode.NOT_DEL_HAS_INCOME);
		}
		
		bmpAccountRepository.delete(id);
		return akResultHelper.buildSuccessAkResult(null);
	}
	
	/**
	 * 初始化配置
	 * @param modelMap
	 */
	@Override
	public void homeSetting(ModelMap modelMap,Long c_accountId,HttpServletResponse response){
		//查询用户账户列表
		List<BmpAccount> bmpAccounts = findByUserId(AuthUtils.getUserId());
		modelMap.put("bmpAccounts", bmpAccounts);
		String coinType = "";
		if(null==c_accountId){
			//账户名没有，设置默认
			if(CollectionUtils.isNotEmpty(bmpAccounts)){
				BmpAccount bmpAccount = bmpAccounts.get(0);
				c_accountId = bmpAccount.getId();
				Cookie cookie = new Cookie(ApolloConstants.COOKIE_ACCOUNT, ""+c_accountId);
				cookie.setPath("/");
//				cookie.setMaxAge(tokenHelper.getExpiration());
				response.addCookie(cookie);
				coinType = bmpAccount.getCoinType();
				
			}
		}
		if(null!=c_accountId){
			BmpAccount bmpAccount = findOne(c_accountId);
			modelMap.put("bmpAccount", bmpAccount);
			coinType = bmpAccount.getCoinType();
		}
		modelMap.put("accountId", c_accountId);
		modelMap.put("email", AuthUtils.getUserName());
		modelMap.put("coinType", coinType);
		modelMap.put("mobile", AuthUtils.getMobile());
	}
}
